from mt4_client import MT4Client, OrderType
import time
from datetime import datetime
from typing import List, Optional
import math
import config

class MartinStrategy:
    def __init__(self, client: MT4Client, symbol: str = "ETHUSD", direction: int = 1):
        self.client = client
        self.symbol = symbol
        self.magic = config.TRADE_CONFIG['magic']
        
        # 获取货币对特定的策略配置
        strategy_config = config.SYMBOL_STRATEGY_CONFIG.get(symbol, config.SYMBOL_STRATEGY_CONFIG['DEFAULT'])
        
        # 策略参数
        self.lots = strategy_config['lots_range']['base']  # 初始手数
        self.tp = strategy_config['tp_range']['base']  # 止盈点数
        self.net = strategy_config['net_range']['base']  # 网格间距
        self.half_close = 7  # 部分平仓阈值
        self.step = strategy_config['step']  # 手数递增步长
        self.direct = direction  # 0空单，1多单
        self.same_order = strategy_config['same_order']  # 维持相同手数的单数
        self.stop_loss_percent = strategy_config['stop_loss_percent']  # 止损百分比
        self.stop_loss_price = 0  # 止损价格
        self.stop_new_orders = False  # 是否停止开启新订单
        self.open_line = 0  # 开仓线
        
        # 打印策略参数
        print(f"\n{symbol} 策略参数:")
        print(f"初始手数: {self.lots}")
        print(f"止盈点数: {self.tp}")
        print(f"网格间距: {self.net}")
        print(f"手数递增步长: {self.step}")
        print(f"维持相同手数单数: {self.same_order}")
        print(f"止损百分比: {self.stop_loss_percent}")
        
    def calculate_current_orders(self) -> int:
        """计算当前订单数量"""
        positions = self.client.get_positions()
        buys = 0
        sells = 0
        
        for pos in positions:
            if pos.symbol == self.symbol and pos.magic == self.magic:
                if pos.type == OrderType.BUY.value:
                    buys += 1
                elif pos.type == OrderType.SELL.value:
                    sells += 1
                    
        if buys > 0:
            return buys
        else:
            return -sells
            
    def lots_optimized(self) -> float:
        """计算优化后的手数"""
        positions = self.client.get_positions()
        current_lots = 0
        orders = 0
        
        for pos in positions:
            if pos.symbol == self.symbol and pos.magic == self.magic:
                if current_lots == 0:
                    current_lots = pos.lots
                    orders += 1
                elif current_lots == pos.lots:
                    orders += 1
                elif current_lots > pos.lots:
                    break
                    
        if orders == 0:
            return self.lots
        elif orders < self.same_order:
            return current_lots
        else:
            new_lots = current_lots * self.step
            if new_lots - current_lots >= 0.01:
                return new_lots
            else:
                return current_lots + 0.01
                
    def check_for_close(self) -> bool:
        """检查平仓条件"""
        positions = self.client.get_positions()
        if not positions:
            return False
            
        # 检查止损条件
        total_loss = 0
        account = self.client.get_account_info()
        market = self.client.get_market_info(self.symbol)
        
        for pos in positions:
            if pos.symbol == self.symbol and pos.magic == self.magic:
                total_loss += pos.profit + pos.swap
                # 检查价格是否触及止损线
                if self.stop_loss_price > 0:
                    if (self.direct == 1 and market.bid < self.stop_loss_price) or \
                       (self.direct == 0 and market.ask > self.stop_loss_price):
                        self.close_all_orders()
                        print(f"价格触及止损线 {self.stop_loss_price}，平掉所有订单")
                        return True
                
        if total_loss < -account.balance * self.stop_loss_percent:
            self.close_all_orders()
            return True
            
        return False
        
    def check_for_open(self) -> None:
        """检查开仓条件"""
        if self.stop_new_orders:
            return
            
        market = self.client.get_market_info(self.symbol)
        if self.direct == 0:  # 空单
            self.client.open_order(
                symbol=self.symbol,
                type=OrderType.SELL.value,
                lots=self.lots,
                sl=self.stop_loss_price if self.stop_loss_price > 0 else 0,
                tp=market.bid - self.tp * market.point,
                magic=self.magic
            )
        elif self.direct == 1:  # 多单
            self.client.open_order(
                symbol=self.symbol,
                type=OrderType.BUY.value,
                lots=self.lots,
                sl=self.stop_loss_price if self.stop_loss_price > 0 else 0,
                tp=market.ask + self.tp * market.point,
                magic=self.magic
            )
                
    def net(self) -> None:
        """网格加仓"""
        if self.stop_new_orders:
            return
            
        positions = self.client.get_positions()
        if not positions:
            return
            
        market = self.client.get_market_info(self.symbol)
        min_buy_price = float('inf')
        max_sell_price = float('-inf')
        buys = sells = 0
        
        for pos in positions:
            if pos.symbol == self.symbol and pos.magic == self.magic:
                if pos.type == OrderType.BUY.value:
                    buys += 1
                    if buys == 1 or pos.open_price < min_buy_price:
                        min_buy_price = pos.open_price
                elif pos.type == OrderType.SELL.value:
                    sells += 1
                    if sells == 1 or pos.open_price > max_sell_price:
                        max_sell_price = pos.open_price
                        
        cur_lots = self.lots_optimized()
        
        if self.direct == 0 and sells > 0 and market.bid - max_sell_price >= self.net * market.point:
            # 空单加仓
            self.client.open_order(
                symbol=self.symbol,
                type=OrderType.SELL.value,
                lots=cur_lots,
                sl=self.stop_loss_price if self.stop_loss_price > 0 else 0,
                tp=0,
                magic=self.magic
            )
            self.modify_orders()
        elif self.direct == 1 and buys > 0 and min_buy_price - market.ask >= self.net * market.point:
            # 多单加仓
            self.client.open_order(
                symbol=self.symbol,
                type=OrderType.BUY.value,
                lots=cur_lots,
                sl=self.stop_loss_price if self.stop_loss_price > 0 else 0,
                tp=0,
                magic=self.magic
            )
            self.modify_orders()
            
    def modify_orders(self) -> None:
        """修改所有订单的止盈"""
        positions = self.client.get_positions()
        if not positions:
            return
            
        # 计算平均价格
        total_lots = 0
        total_price = 0
        
        for pos in positions:
            if pos.symbol == self.symbol and pos.magic == self.magic:
                total_lots += pos.lots
                total_price += pos.lots * pos.open_price
                
        if total_lots == 0:
            return
            
        avg_price = total_price / total_lots
        market = self.client.get_market_info(self.symbol)
        
        # 修改每个订单的止盈
        for pos in positions:
            if pos.symbol == self.symbol and pos.magic == self.magic:
                if pos.type == OrderType.BUY.value:
                    new_tp = avg_price + self.tp * market.point
                else:
                    new_tp = avg_price - self.tp * market.point
                    
                self.client.modify_order(pos.ticket, 0, new_tp)
                
    def close_all_orders(self) -> None:
        """平掉所有订单"""
        positions = self.client.get_positions()
        for pos in positions:
            if pos.symbol == self.symbol and pos.magic == self.magic:
                self.client.close_order(pos.ticket)
                
    def run(self) -> None:
        """运行策略"""
        try:
            # 订阅价格更新
            self.client.subscribe_price(self.symbol)
            
            print(f"开始运行马丁策略，交易品种: {self.symbol}")
            print("按 Ctrl+C 停止策略")
            
            while True:
                # 获取价格更新
                price_update = self.client.get_price_update()
                
                if price_update:
                    # 检查开仓条件
                    if self.calculate_current_orders() == 0:
                        self.check_for_open()
                        
                    # 检查平仓条件
                    self.check_for_close()
                    
                    # 检查网格加仓条件
                    self.net()
                    
                # 短暂休眠，避免CPU占用过高
                time.sleep(0.001)
                
        except KeyboardInterrupt:
            print("\n停止策略...")
        except Exception as e:
            print(f"发生错误: {str(e)}")
        finally:
            # 取消订阅
            self.client.unsubscribe_price(self.symbol)
            print("策略已停止")

    def stop(self) -> None:
        """停止策略"""
        self.stop_new_orders = True
        print("策略停止开启新订单")

if __name__ == "__main__":
    # 创建MT4客户端
    client = MT4Client()
    
    # 创建并运行策略
    strategy = MartinStrategy(client)
    strategy.run() 